<?php

/****/

define('VKLANG_CACHE_DIR', 'C:/windows/temp/vklang/cache');
define('VKLANG_CONF_DIR', '../php/conf');
define('VKLANG_CONF_LANGS_CSV', 'official_langs.csv');
define('VKLANG_GEOIP_CLASS', 'lib/ip2c/geoip.lib.php');
define('VKLANG_GEOIP_DAT', 'lib/ip2c/GeoIP.dat');
//define('VKLANG_ENCODING', 'UTF-8');
define('VKLANG_ENCODING', 'cp1251');
define('VKLANG_HTML_ENCODING', '1');

if (isset($_SERVER['SHELL'])) {
  define('VKLANG_DEBUG_MODE', $_SERVER['SHELL']);
} else {
  define('VKLANG_DEBUG_MODE', 0);
}

/*****/
/*<CLASS DEF VKLang vklang>*/

/*<CLASS CONST>*/
define('VKLANG_CONST_LT_INDEX', 0);
define('VKLANG_CONST_GT_INDEX', 1);
define('VKLANG_CONST_EQ_INDEX', 2);
define('VKLANG_CONST_NE_INDEX', 3);

define('VKLANG_CONST_ORIGINAL_OBJ', 1);
define('VKLANG_CONST_CURRENT_OBJ', 2);
define('VKLANG_CONST_OBJ_TAG', 'VKLANG');

define('VKLANG_CONST_PATTERN_START', 0);
define('VKLANG_CONST_PATTERN_END', 1);
define('VKLANG_CONST_PATTERN_EXACT', 2);

define('VKLANG_CONST_ERROR_FORMAT_FAILED', 1);
/*</CLASS CONST>*/

/*<CLASS VAR>*/
global $_vklang_var_locale;
global $_vklang_var_conf;
global $_vklang_var_last_error; $_vklang_var_last_error = 0;

global $_vklang_var_cached_time; $_vklang_var_cached_time = 0;
/*</CLASS VAR>*/

/*<CLASS STATIC VAR>*/
global $_VKLANG_STATIC_OBJ_MAP; $_VKLANG_STATIC_OBJ_MAP = array(VKLANG_CONST_ORIGINAL_OBJ => 'original', VKLANG_CONST_CURRENT_OBJ => 'current');
/*</CLASS STATIC VAR>*/

/*<CLASS CONSTRUCTOR>*/
function vklang_init($locale = false, $ip = false, $force_ip = false) {
  /*<CLASS GLOBAL>*/
  global $VKLangConfig;
  /*</CLASS GLOBAL>*/
  
  if (!isset($VKLangConfig['locales'])) {
    $locales_file = VKLANG_CACHE_DIR.'/locales.conf.php';
    
    if (!file_exists(VKLANG_CACHE_DIR)) {
      mkdir(VKLANG_CACHE_DIR, 0777, true);
    }
    
    if (VKLANG_DEBUG_MODE || !file_exists($locales_file)) {
      /*<IF CLASS>*//*
      if (!class_exists('VKLangInit')) {
        require("init_parser.php");
      }
      *//*</IF CLASS>*/
      /*<IF PROC>*/
      if (!defined('VKLANG_INIT_LOADED')) {
        require("init_parser_proc.php");
      }
      /*</IF PROC>*/
      _vklang_init_initParser($locales_file);
    }
    require $locales_file;
  }
  
  if (!$locale) {
    if (!class_exists('GeoIP')) {
      require VKLANG_GEOIP_CLASS;
    }
    
    $country_codes = vklang_getLocalesFromHeader();
    $country_code = $country_codes[0];
    
    if (!$country_code) {
      if (!$ip) {
        $ip = $_SERVER['HTTP_X_REAL_IP'];
      }
    
      if ($ip) {
        $geoip = geoip_open();
        $country_code = geoip_country_code_by_addr($geoip, $ip);
        geoip_close($geoip);
      }
    }
    $locale = $country_code;
  }
  
  if (!is_dir(VKLANG_CACHE_DIR)) {
    mkdir(VKLANG_CACHE_DIR);
  }
  
  if (!is_dir(VKLANG_CACHE_DIR.'/conf')) {
    mkdir(VKLANG_CACHE_DIR.'/conf');
    vklang_generateConfig();
  }
  
  if ($locale) {
    if (!vklang_setLocale($locale)) {
      return false;
    }
  }
}
/*</CLASS CONSTRUCTOR>*/

/*<CLASS FUNC>*/
function vklang_generateConfig() {
  $locales_file = VKLANG_CACHE_DIR.'/locales.conf.php';
  require $locales_file;
  /*<IF CLASS>*//*
  if (!class_exists('VKLangInit')) {
    require("init_parser.php");
  }
  *//*</IF CLASS>*/
  /*<IF PROC>*/
  if (!defined('VKLANG_INIT_LOADED')) {
    require("init_parser_proc.php");
  }
  /*</IF PROC>*/
  foreach ($VKLangConfig['locales'] as $locale) {
    $json_file = VKLANG_CONF_DIR.'/'.$locale.'.json';
    $php_file = VKLANG_CACHE_DIR.'/conf/'.$locale.'.php';
    _vklang_init_parseConfig($json_file, $php_file);
  }
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function vklang_getLocalesFromHeader() {
  if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
    return array();
  }
  $langs = array();
  foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $k => $pref) {
    if (($i = strpos($pref, ';q=')) !== false) {
      $q = floatval(substr($pref, $i + 3));
      $locale = substr($pref, 0, $i); 
    } else {
      $q = 1;
      $locale = $pref;
    }
    $lang_reg = explode('-', $locale, 2);
    $lang_reg[0] = strtolower($lang_reg[0]);
    if ($lang_reg[1]) $lang_reg[1] = strtoupper($lang_reg[1]);
    $locale = implode('-', $lang_reg);
    $langs[$locale] = $q;
  }
  arsort($langs);

  return array_keys($langs);
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function vklang_setLocale($locale) {
  /*<CLASS GLOBAL>*/
  global $_vklang_var_conf, $_vklang_var_locale, $_vklang_var_cached_time;
  /*</CLASS GLOBAL>*/
  
  $json_file = VKLANG_CONF_DIR.'/'.$locale.'.json';

  if (!file_exists($json_file)) {
    list($locale) = explode('-', $locale);
    $json_file = VKLANG_CONF_DIR.'/'.$locale.'.json';
    if (!file_exists($json_file)) {
      return false;
    }
  }
  
  $json_time = filectime($json_file);
  $php_file = VKLANG_CACHE_DIR.'/conf/'.$locale.'.php';
  
  if (VKLANG_DEBUG_MODE || !file_exists($php_file) || $json_time > filectime($php_file)) {
    /*<IF CLASS>*//*
    if (!class_exists('VKLangInit')) {
      require("init_parser.php");
    }
    *//*</IF CLASS>*/
    /*<IF PROC>*/
    if (!defined('VKLANG_INIT_LOADED')) {
      require("init_parser_proc.php");
    }
    /*</IF PROC>*/
    _vklang_init_parseConfig($json_file, $php_file);
  }
  
  require $php_file;

  if ($VKLangConfig === null) {
    return false;
  }
  
  $_vklang_var_conf = $VKLangConfig['config'];
  $_vklang_var_conf['cached'] = array();
  $_vklang_var_locale = $locale;
  $_vklang_var_cached_time = false;
  
  return true;
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function vklang_format() {
  /*<CLASS GLOBAL>*/
  global $_vklang_var_last_error, $_vklang_var_conf;
  /*</CLASS GLOBAL>*/
  $res = "";
  $cur = 0;
  
  $count = func_num_args() - 1;
  if ($count < 0) {
    return '';
  }
  
  $str = func_get_arg(0);
  
  $len = strlen($str);
  
  if (!isset($_vklang_var_conf['cached'][$str])) {
    $cached = array();
    $n = 0;
    while (($pos = strpos($str, '{', $cur)) !== false) {
      $res .= str_replace('}}', '}', substr($str, $cur, $pos - $cur));
      $cur = $pos + 1;
      if ($pos == $len - 1) {
        $_vklang_var_last_error = VKLANG_CONST_ERROR_FORMAT_FAILED;
        $_vklang_var_conf['cached'][$str] = false;
        return $str;
      }
      switch ($str[$cur]) {
        case '{':
          $res .= '{';
          $cur++;
          break;
        default:
          $end = strpos($str, '}', $cur);
          while ($end !== false && $end < $len - 1 && $str[$end + 1] == '}') {
            $end = strpos($str, '}', $end + 2);
          }
          if ($end === false) {
            $_vklang_var_last_error = VKLANG_CONST_ERROR_FORMAT_FAILED;
            $_vklang_var_conf['cached'][$str] = false;
            return $str;
          }
          $rule = str_replace(array('{{', '}}'), array('{', '}'), substr($str, $cur, $end - $cur));
          $cur = $end + 1;
          if (strlen($rule) > 0) {
            $arr = explode(':', $rule, 3);
            if (count($arr) > 2) {
              list($tag_id, $rule_name, $rule) = $arr;
            } else {
              list($tag_id, $rule_name) = $arr;
              $rule = '';
            }
            
            $res .= "\x1".$n."\x2";
            if ($rule_name && isset($_vklang_var_conf['rules'][$rule_name])) {
              if ($rule && $_vklang_var_conf['rules'][$rule_name]['type'] == 'flex') {
                $rule = explode(':', $rule);
              }
              $replace["\x1".$n."\x2"] = array($tag_id, $rule_name, $rule);
            } else {
              $replace["\x1".$n."\x2"] = array($tag_id);
            }
            $n++;
          }
          break;
      }
    }
    if ($cur < $len) $res .= substr(str_replace('}}', '}', $str), $cur, $len - $cur);
    $cached['res'] = $res;
    $cached['replace'] = $replace;
    $_vklang_var_conf['cached'][$str] = $cached;
  } else {
    $cached = $_vklang_var_conf['cached'][$str];
    if ($cached === false) {
      $_vklang_var_last_error = VKLANG_CONST_ERROR_FORMAT_FAILED;
      return $str;
    }
  }
  
  $str = $cached['res'];
  if ($count == 0) {
    return $str;
  }
  $from = array();
  $to = array();

  foreach ($cached['replace'] as $match => $replace) {
    list ($tag_id, $rule_name, $rule) = $replace;
    if ($tag_id >= $count) {
      $str = str_replace($match, '', $str);
      continue;
    }
    $arg = func_get_arg($tag_id + 1);
    $from[] = $match;
    if ($rule_name) {
      $rule_conf = $_vklang_var_conf['rules'][$rule_name];
      switch ($rule_conf['type']) {
        case 'time':
          $to[] = _vklang_parseDate($rule_conf, $_vklang_var_conf['config'][$rule_conf['conf']], $arg, $rule);
          break;
        case 'numeric':
          $to[] = _vklang_parseNumeric($rule_conf, $arg, $rule);
          break;
        case 'flex':
          $data = array(0 => VKLANG_CONST_OBJ_TAG, VKLANG_CONST_ORIGINAL_OBJ => $arg, VKLANG_CONST_CURRENT_OBJ => $arg);
          if ($rule) {
            foreach ($rule as $r_name) {
              $r = $_vklang_var_conf['rules'];
              if (isset($r[$r_name])) {
                _vklang_parseFlexPipe($r[$r_name], $data);
              }
            }
          }
          $to[] = _vklang_parseFlex($rule_conf, $data);
          break;
        case 'switch':
          $to[] = _vklang_parseSwitch($rule_conf, $arg, $rule);
          break;
        default:
          $to[] = $arg;
          break;
      }
    } else {
      $to[] = $arg;
    }
  }
  $str = str_replace($from, $to, $str);
  return $str;
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function _vklang_parseSwitch($rule_conf, $data, $params) {
  $params = explode(':', $params);
  $params_len = count($params);
  if ($params_len == 1) return $params[0];
  foreach($rule_conf['variants'] as $variant) {
    if (_vklang_checkCondition($data, $variant[0][0], $variant[0][1], $variant[0][2])) {
      return $variant[1] < $params_len ? $params[$variant[1]] : $params[0];
    }
  }
  return $params[0];
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function _vklang_parseNumeric($rule_conf, $data, $params) {
  
  $variant = false;
  $params = explode(':', $params);
  if (count($params) <= 1) {
    $variant = $params[0];
  } else {
    $data_int = intval($data);
    $data_pos = abs($data);
    if ($data != $data_int) {
      $variant = $rule_conf['float'];
    } else if (isset($rule_conf['variants'])) {
      foreach ($rule_conf['variants'] as $rule) {
        $mod = $rule[0] ? $data_pos % $rule[0] : $data_pos;
        if (in_array($mod, $rule[1])) {
          $variant = $rule[2];
          break;
        }
      }
      if ($variant === false) {
        $variant = $rule_conf['int'];
      }
    }
  }
  
  $variant = isset($params[$variant]) ? $params[$variant] : $params[0];
  
  $variant = str_replace('%%', '<P>', $variant);
  
  if (strpos($variant, '%n') !== false) {
    $data_str = "{$data}";
    $dot = strpos($data_str, '.');
    $decimals = ($dot === false) ? 0 : (strlen($data_str) - $dot - 1);
    if (strlen($rule_conf['delimiter']) > 1) {
      $data_str = number_format($data, $decimals, $rule_conf['decimal'], '%');
      $data_str = str_replace('%', $rule_conf['delimiter'], $data_str);
    } else {
      $data_str = number_format($data, $decimals, $rule_conf['decimal'], $rule_conf['delimiter']);
    }
    $variant = str_replace('%n', $data_str, $variant);
  }

  $data = str_replace('<P>', '%', sprintf($variant, $data));
  
  return $data;
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function _vklang_parseDate($rule_conf, $time_config, $data, $params) {
  /*<CLASS GLOBAL>*/
  global $_vklang_var_cached_time, $_vklang_var_conf;
  /*</CLASS GLOBAL>*/
  
  $data = intval($data);
  
  $pattern = $rule_conf['patterns'];
  
  if ($_vklang_var_cached_time === false) {
    $cur_time = time();
    $_vklang_var_cached_time = array();
    foreach ($_vklang_var_conf['cached_time'] as $time_format => $v) {
      $_vklang_var_cached_time[$time_format] = strtotime($time_format, $cur_time);
    }
  }
  //var_dump($pattern);
  
  $time_format = '';
  foreach ($pattern as $time_rule) {
    if (is_array($time_rule)) {
      if ($data >= $_vklang_var_cached_time[$time_rule[0]] && $data < $_vklang_var_cached_time[$time_rule[1]]) {
        $time_format = $time_rule[2];
        break;
      }
    } else {
      $time_format = $time_rule;
    }
  }
  
  $date = getdate($data);

  if (!$time_config['24H']) {
    $am_pm = ($date['hours'] > 11) ? $time_config['PM'] : $time_config['AM'];
    $date['hours'] = ($date['hours'] % 12 == 0) ? 12 : $date['hours'] % 12;
  }
  
  if ($time_config['subpatterns']) {
    foreach ($time_config['subpatterns'] as $subpattern_name => $subpattern) {
      if (strpos($time_format, '{'.$subpattern_name.'}') !== false) {
        $period = $subpattern['period'];
        $sub_rule = isset($subpattern['rules'][$date[$period]]) ? $subpattern['rules'][$date[$period]] : $subpattern['rules']['default'];
        $time_format = str_replace('{'.$subpattern_name.'}', $sub_rule, $time_format);
      }
    }
  }

  $nn = $date['minutes'] > 9 ? $date['minutes'] : '0'.$date['minutes'];
  $ss = $date['seconds'] > 9 ? $date['seconds'] : '0'.$date['seconds'];

  $num_day = $date['mday'] > 9 ? $date['mday'] : '0'.$date['mday'];
  $num_hour = $date['hours'] > 9 ? $date['hours'] : '0'.$date['hours'];
  $mm = $date['mon'] > 9 ? $date['mon'] : '0'.$date['mon'];
  $year = $date['year'] + $time_config['year_offset'];
  
  foreach ($time_config['months'] as $month_rule_name => $months) {
    if (strpos($time_format, '{'.$month_rule_name.'}') !== false) {
      $time_format = str_replace('{'.$month_rule_name.'}', $months[$date['mon']], $time_format);
    }
  }    

  $time_format = strtr($time_format, array(
    '{hour}'        => $date['hours'],
    '{h}'           => $date['hours'],
    '{hh}'          => $num_hour,
    '{minute}'      => $nn,
    '{n}'           => $date['minutes'],
    '{nn}'          => $nn,
    '{day}'         => $date['mday'],
    '{d}'           => $date['mday'],
    '{dd}'          => $num_day,
    '{m}'           => $date['mon'],
    '{mm}'          => $mm,
    '{year}'        => $year,
    '{yyyy}'        => $year,
    '{short_year}'  => $year % 100,
    '{yy}'          => $year % 100,
    '{second}'      => $ss,
    '{s}'           => $date['seconds'],
    '{ss}'          => $ss,
    '{am_pm}'       => $am_pm
  ));
  
  return $time_format;
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function _vklang_parseFlexPipe($rule_conf, &$data) {
  /*<CLASS GLOBAL>*/
  global $_vklang_var_conf, $_VKLANG_STATIC_OBJ_MAP;
  /*</CLASS GLOBAL>*/
      
  $conditions = _vklang_checkConditions($data, $rule_conf['conditions']);
  
  foreach ($rule_conf['from'] as $idx => $from) {
    $had_field = false;
    $result = $from;
    
    foreach ($rule_conf['from_obj'][$idx] as $obj_type => $from_fields) {
      foreach ($from_fields as $from_field) {
        if (isset($data[$obj_type][$from_field])) {
          $had_field = true;
          $result = str_replace('{'.$_VKLANG_STATIC_OBJ_MAP[$obj_type].'.'.$from_field.'}', $data[$obj_type][$from_field], $result);
        }
      }
    }

    if (!$had_field) { continue; }
    
    if ($result && isset($rule_conf['patterns'])) {
      $patterns = $rule_conf['patterns'];
      
      $processed = false;
      
      if (isset($patterns['~~']) && isset($patterns['~~'][$result])) {
        $cond = strtok($patterns['~~'][$result], ',');
        $res = strtok(',');
        while ($cond !== false) {
          if ($cond === 0 || $conditions[$cond]) {
            $result = $res;
            $processed = true;
            break;
          }
          $cond = strtok(',');
          $res = strtok(',');
        }
      }
      
      $last_flexible = false;
      $first_flexible = false;
      if (!$processed) {
        $res_len = strlen($result);
        $last_letter = $result[$res_len - 1];
        if ($res_len > 1) {
          $last_flexible = (!$rule_conf['flexible']) || strpos($rule_conf['flexible'], $last_letter) !== false;
          if ($last_flexible && isset($rule_conf['patterns']['~'.$last_letter])) {
            $cond = strtok($rule_conf['patterns']['~'.$last_letter], ',');
            $pat_len = strtok(',');
            $pat = strtok(',');
            $res = strtok(',');
            while($cond !== false) {
              if ($conditions[$cond] && (strrpos($result, $pat) === $res_len - $pat_len)) {
                $result = substr($result, 0, $res_len - $pat_len).$res;
                $processed = true;
                break;
              }
              $cond = strtok(',');
              $pat_len = strtok(',');
              $pat = strtok(',');
              $res = strtok(',');
            }
          }
        }
  
        $first_letter = $result[0];
        if (!$processed) {
          $first_flexible = (!$rule_conf['flexible']) || strpos($rule_conf['flexible'], $first_letter) !== false;
          if (isset($rule_conf['patterns'][$first_letter.'~'])) {
            $cond = strtok($rule_conf['patterns'][$first_letter.'~'], ',');
            $pat_len = strtok(',');
            $pat = strtok(',');
            $res = strtok(',');
            while($cond !== false) {
              if ($conditions[$cond] && (strpos($result, $pat) === 0)) {
                $result = $res.substr($result, $pat_len);
                $processed = true;
                break;
              }
              $cond = strtok(',');
              $pat_len = strtok(',');
              $pat = strtok(',');
              $res = strtok(',');
            }
          }
        }
        
        if (!$processed && isset($rule_conf['patterns']['~']) && ($first_flexible || $last_flexible)) {
          $arr = explode(',', $rule_conf['patterns']['~']);
          $cond = strtok($rule_conf['patterns']['~'], ',');
          $type = strtok(',');
          $res = strtok(',');
          while($cond !== false) {
            if ($conditions[$cond] && $type == VKLANG_CONST_PATTERN_START && $last_flexible) {
              $result = $res.$result;
              break;
            } else if ($conditions[$cond] && $type == VKLANG_CONST_PATTERN_END && $first_flexible) {
              $result = $result.$res;
              break;
            }
            $cond = strtok(',');
            $type = strtok(',');
            $res = strtok(',');
          }
        }
      }
    }
    
    $data[$rule_conf['to_obj'][$idx][0]][$rule_conf['to_obj'][$idx][1]] = $result;
  }
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function _vklang_parseFlex($rule_conf, $data) {
  /*<CLASS GLOBAL>*/
  global $_vklang_var_conf, $_VKLANG_STATIC_OBJ_MAP;
  /*</CLASS GLOBAL>*/
  
  $conditions = isset($rule_conf['conditions']) ? _vklang_checkConditions($data, $rule_conf['conditions']) : array(0 => true);
  
  $from = $rule_conf['from'][0];
  
  $had_field = false;
  $result = $from;
  foreach ($rule_conf['from_obj'][0] as $obj_type => $from_fields) {
    foreach ($from_fields as $from_field) {
      if (isset($data[$obj_type][$from_field])) {
        $had_field = true;
        $result = str_replace('{'.$_VKLANG_STATIC_OBJ_MAP[$obj_type].'.'.$from_field.'}', $data[$obj_type][$from_field], $result);
      }
    }
  }

  if (!$had_field || !isset($rule_conf['patterns'])) { return $result; }
  
  $patterns = $rule_conf['patterns'];
  
  $processed = false;
  
  if (isset($patterns['~~']) && isset($patterns['~~'][$result])) {
    $cond = strtok($patterns['~~'][$result], ',');
    $res = strtok(',');
    while ($cond !== false) {
      if ($cond === 0 || $conditions[$cond]) {
        $result = $res;
        $processed = true;
        break;
      }
      $cond = strtok(',');
      $res = strtok(',');
    }
  }
  
  $last_flexible = false;
  $first_flexible = false;
  if (!$processed) {
    $res_len = strlen($result);
    $last_letter = $result[$res_len - 1];
    if ($res_len > 1) {
      $last_flexible = (!$rule_conf['flexible']) || strpos($rule_conf['flexible'], $last_letter) !== false;
      if ($last_flexible && isset($rule_conf['patterns']['~'.$last_letter])) {
        $cond = strtok($rule_conf['patterns']['~'.$last_letter], ',');
        $pat_len = strtok(',');
        $pat = strtok(',');
        $res = strtok(',');
        while($cond !== false) {
          if ($conditions[$cond] && (strrpos($result, $pat) === $res_len - $pat_len)) {
            $result = substr($result, 0, $res_len - $pat_len).$res;
            $processed = true;
            break;
          }
          $cond = strtok(',');
          $pat_len = strtok(',');
          $pat = strtok(',');
          $res = strtok(',');
        }
      }
    }

    $first_letter = $result[0];
    if (!$processed) {
      $first_flexible = (!$rule_conf['flexible']) || strpos($rule_conf['flexible'], $first_letter) !== false;
      if (isset($rule_conf['patterns'][$first_letter.'~'])) {
        $cond = strtok($rule_conf['patterns'][$first_letter.'~'], ',');
        $pat_len = strtok(',');
        $pat = strtok(',');
        $res = strtok(',');
        while($cond !== false) {
          if ($conditions[$cond] && (strpos($result, $pat) === 0)) {
            $result = $res.substr($result, $pat_len);
            $processed = true;
            break;
          }
          $cond = strtok(',');
          $pat_len = strtok(',');
          $pat = strtok(',');
          $res = strtok(',');
        }
      }
    }
    
    if (!$processed && isset($rule_conf['patterns']['~']) && ($first_flexible || $last_flexible)) {
      $arr = explode(',', $rule_conf['patterns']['~']);
      $cond = strtok($rule_conf['patterns']['~'], ',');
      $type = strtok(',');
      $res = strtok(',');
      while($cond !== false) {
        if ($conditions[$cond] && $type == VKLANG_CONST_PATTERN_START && $last_flexible) {
          $result = $res.$result;
          break;
        } else if ($conditions[$cond] && $type == VKLANG_CONST_PATTERN_END && $first_flexible) {
          $result = $result.$res;
          break;
        }
        $cond = strtok(',');
        $type = strtok(',');
        $res = strtok(',');
      }
    }
  }
  
  return $result;
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function _vklang_checkConditions($obj, $conditions) {
  $res = array(0 => true);
  if (!$conditions) return $res;
  foreach ($conditions as $i => $cond) {
    $arr = $obj[$cond[1]];
    $res[$i] = _vklang_checkCondition($arr, $cond[0], $cond[2], $cond[3]);
  }
  return $res;
}
/*</CLASS FUNC>*/

/*<CLASS FUNC>*/
function _vklang_checkCondition($arr, $op, $key, $val) {
  switch ($op) {
    case VKLANG_CONST_EQ_INDEX:
      if ($arr[$key] != $val) return false;
      break;
    case VKLANG_CONST_NE_INDEX:
      if ($arr[$key] == $val) return false;
      break;
    case VKLANG_CONST_GT_INDEX:
      if ($arr[$key] <= $val) return false;
      break;
    case VKLANG_CONST_LT_INDEX:
      if ($arr[$key] >= $val) return false;
      break;
  }
  return true;
}
/*</CLASS FUNC>*/

/*</CLASS DEF>*/